home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 1.0 beta / flock-1.0RC3.en-US.win32.exe / flock / modules / FlockScheduler.jsm < prev    next >
Text File  |  2007-10-18  |  4KB  |  120 lines

  1. // BEGIN FLOCK GPL
  2. // 
  3. // Copyright Flock Inc. 2005-2007
  4. // http://flock.com
  5. // 
  6. // This file may be used under the terms of of the
  7. // GNU General Public License Version 2 or later (the "GPL"),
  8. // http://www.gnu.org/licenses/gpl.html
  9. // 
  10. // Software distributed under the License is distributed on an "AS IS" basis,
  11. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. // for the specific language governing rights and limitations under the
  13. // License.
  14. // 
  15. // END FLOCK GPL
  16.  
  17. const CC = Components.classes;
  18. const CI = Components.interfaces;
  19. const CR = Components.results;
  20.  
  21. var EXPORTED_SYMBOLS = ["FlockScheduler"];
  22.  
  23. /**
  24.  * FlockScheduler.schedule() - A cheap scheduler for javascript tasks.
  25.  *
  26.  * @param object[] aTimers (in) (optional)
  27.  *      If provided, any timers created will be stored in this array
  28.  *      so the caller can cancel them early.
  29.  * @param float aSlice (in)
  30.  *      Maximum timeslice in seconds. 0.5 or less is a good value.
  31.  * @param float aPercent (in)
  32.  *      Percent of wall-clock time that should be spent executing the task.
  33.  *      For example, 20 = one fifth of the time.
  34.  * @param function aTask (in)
  35.  *      A generator taking a function that evaluates to true if it should
  36.  *      yield, like this:
  37.  *
  38.  *        function task(should_yield) {
  39.  *          while (some_condition) {
  40.  *            do some work...
  41.  *            if (should_yield()) {
  42.  *              yield;
  43.  *            }
  44.  *          }
  45.  *        }
  46.  *
  47.  * @return nothing
  48.  *
  49.  * NOTE: should_yield() is fairly cheap but in a tight inner loop it might
  50.  *       make sense to call it every N cycles
  51.  */
  52. var FlockScheduler = {
  53.   schedule: function schedule(aTimers, aSlice, aPercent, aTask) {
  54.  
  55.     // convert percent to ratio
  56.     var ratio = aPercent / 100.0;
  57.  
  58.     // convert slice to milliseconds
  59.     var slice = aSlice * 1000.0;
  60.  
  61.     // A helper to get the current time as milliseconds.
  62.     function milliseconds() { return (new Date ()).getTime(); }
  63.     var wall_start = milliseconds();
  64.     var process_time = 0;
  65.     var process_start = 0;
  66.  
  67.     // A function the task can use to decide whether to yield its timeslice.
  68.     function should_yield() {
  69.       var now = milliseconds();
  70.       var so_far = now - process_start;
  71.       var wall_time = now - wall_start;
  72.       return (so_far >= slice) ||
  73.              ((wall_time * ratio) < (process_time + so_far));
  74.     }
  75.  
  76.     // A generator is (among other things) a function that calls yield().
  77.     // To resume execution at the point of suspension by yield(), call the
  78.     // generator's .next() method.
  79.     // See https://bugzilla.mozilla.org/show_bug.cgi?id=326466
  80.     var generator = aTask(should_yield);
  81.     var timer = CC["@mozilla.org/timer;1"].createInstance(CI.nsITimer);
  82.  
  83.     var callback = {
  84.       notify: function FlockScheduler_callback_notify() {
  85.         var wall_time = milliseconds() - wall_start;
  86.  
  87.         if (process_time > (wall_time * ratio)) {
  88.           // We've spent more time than we're supposed to; skip this cycle.
  89.           return;
  90.         }
  91.  
  92.         process_start = milliseconds();
  93.         try {
  94.           // Resume execution where the function yield()ed.
  95.           generator.next();
  96.         } catch (err if err instanceof StopIteration) {
  97.           // The task is complete; stop timer and destroy it.
  98.           timer.cancel();
  99.           if (aTimers) {
  100.             for (var i = 0; i < aTimers.length; i++) {
  101.               if (aTimers[i] === timer) {
  102.                 aTimers.splice(i, 1);
  103.               }
  104.             }
  105.           }
  106.           timer = null;
  107.         }
  108.         process_time += (milliseconds() - process_start);
  109.       }
  110.     };
  111.  
  112.     timer.initWithCallback(callback,
  113.                            Math.round(slice/ratio),
  114.                            CI.nsITimer.TYPE_REPEATING_SLACK);
  115.     if (aTimers) {
  116.       aTimers.push(timer);
  117.     }
  118.   }
  119. };
  120.